<?php
/**
 * 图片上传类
 * 依赖于：
 *      net/dwHttp
 */
class ImgUpload {
    
    protected $_ret = array(
        'code' => 0,
        'msg' => '',
        'url' => '',
        'sha1' => '',
        'width' => 0,
        'height' => 0,
        'mimeType' => '',
        'fileExt' => '',
        'fileSize' => 0,
        'fileName' => '',
        'resultFile' => '',
        'resultFilepath' => '',
    );
    
    protected function _checkType($file){
        switch (strtolower($file['type'])) {
            case 'image/jpeg': $this->_ret['fileExt'] = 'jpg'; break;
            case 'image/gif': $this->_ret['fileExt'] = 'gif'; break;
            case 'image/png': $this->_ret['fileExt'] = 'png'; break;
            case 'image/bmp': $this->_ret['fileExt'] = 'bmp'; break;
            case 'image/tiff': $this->_ret['fileExt'] = 'tif'; break;
        }
        if (! $this->_ret['fileExt']) {
            $this->_ret['msg'] = "illegal file type [{$file['type']}]";
            return false;
        }
        return true;
    }
    
    //待完善
    protected function _checkError($file){
        if (UPLOAD_ERR_OK == $file['error']) return true;
        
        $this->_ret['msg'] = '各种不成功的情况'; // ...
        
        return false;
    }
    
    protected function _checkName($file){
        if (preg_match('/\\0|\:|\/|\\|\?|\^|\*|\<|\>|\$/', $file['name'])) {
            $this->_ret['msg'] = 'illegal file name';
            return false;
        }
        $this->_ret['fileName'] = $file['name'];
        return true;
    }
    
    protected function _checkTmpName($file){
        if (is_uploaded_file($file['tmp_name'])) return true;
        $this->_ret['msg'] = 'found upload attack..';
        return false;
    }
    
    //【待完善】检测文件内部
    protected function _checkFileData($file){
        @$getImaSize = getimagesize($file['tmp_name']);
        if (false === $getImaSize) {
            $this->_ret['msg'] = 'file is not an image';
            return false;
        }
        
        list($width, $height, $type, $attr) = $getImaSize;
        $this->_ret['width'] = $width;
        $this->_ret['height'] = $height;
        $imgTypes = array(
            IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_SWF,
            IMAGETYPE_PSD, IMAGETYPE_BMP, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM,
            IMAGETYPE_JPC, IMAGETYPE_JP2, IMAGETYPE_JPX, IMAGETYPE_JB2,
            IMAGETYPE_SWC, IMAGETYPE_IFF, IMAGETYPE_WBMP, IMAGETYPE_XBM,
            IMAGETYPE_ICO,
        );
        if (in_array($type, $imgTypes)) {
            $this->_ret['mimeType'] = image_type_to_mime_type($type);
            return true;
        } else {
            $this->_ret['msg'] = 'illegal mimetype, not an image';
            return false;
        }
    }
    
    //待完善
    protected function _checkSize($file){
        $this->_ret['fileSize'] = $file['size'];
        return true;
    }
    
    //计算SHA1
    protected function _calcSha1($file){
        $this->_ret['sha1'] = sha1_file($file['tmp_name']);
    }
    
    protected function _check($file){
        if (! $this->_checkType($file)) {
            $this->_ret['code'] = -1;
            return false;
        }
        if (! $this->_checkError($file)) {
            $this->_ret['code'] = -2;
            return false;
        }
        if (! $this->_checkTmpName($file)) {
            $this->_ret['code'] = -3;
            return false;
        }
        if (! $this->_checkFileData($file)) {
            $this->_ret['code'] = -4;
            return false;
        }
        if (! $this->_checkSize($file)) {
            $this->_ret['code'] = -5;
            return false;
        }
        $this->_calcSha1($file);
        return true;
    }
    
}

/**
 * 图片上传客户端
 */
class ImgUploadClient extends ImgUpload {
    protected $_uploadHost;
    
    protected $_imgGroupDir;
    
    function __construct($imgGroupDir = '', $uploadHost = ''){
        @$this->_imgGroupDir = $imgGroupDir ?: $GLOBALS['imgUploadSetup']['imgGroupDir'] ?: 'default/';
        @$this->_uploadHost = $uploadHost ?: $GLOBALS['api']['imgUploadHost'] ?: 'http://res.miku.us/cbupl/upimg.php';
    }
    
    //请求上传接口
    protected function _reqUp($file){
        import('net/dwHttp');
        $http = new dwHttp();
        @$ret = $http->postFile($this->_uploadHost, array(
            'tu' => '@'.$file['tmp_name'].';type='.$this->_ret['mimeType'],
            'fileName' => $file['name'],
            'imgGroupDir' => $this->_imgGroupDir,
        ));
        if (false === $ret) {
            $this->_ret['code'] = -6;
            $this->_ret['msg'] = 'upload failed';
        } else {
            $this->_ret = json_decode($ret, true);
        }
    }
    
    /*
     * 通过接口上传处理程序
     * @param array $_FILES中具体的某个表单域
     */
    function up($file){
        if (! $this->_check($file)) return $this->_ret;
        $this->_reqUp($file);
        return $this->_ret;
    }
    
    //客户端调用接口测试用例
    static function testClient(){
        $client = new ImgUploadClient();
        $ret = $client->up($_FILES['tu']);
        unset($ret['resultFilepath']);
        dump($ret);
    }
}


/**
 * 图片上传服务端
 */
class ImgUploadServer extends ImgUpload {
    protected $_imgBaseDir;
    
    protected $_imgGroupDir;
    
    protected $_imgPreUrl;
    
    function __construct($imgGroupDir = '', $imgPreUrl = '', $imgBaseDir = ''){
        @$this->_imgGroupDir = rtrim('/', $imgGroupDir ?: $GLOBALS['imgUploadSetup']['imgGroupDir'] ?: 'default/') . '/';
        @$this->_imgPreUrl = rtrim('/', $imgPreUrl ?: $GLOBALS['imgUploadSetup']['imgPreUrl'] ?: 'http://res.miku.us/res/img/') . '/';
        @$this->_imgBaseDir = rtrim('/', $imgBaseDir ?: $GLOBALS['imgUploadSetup']['imgBaseDir'] ?: '/home/wwwroot/res.miku.us/res/img/') . '/';
    }
    
    protected function _mkdirs($dir, $mode = 0777){
        if (! is_dir($dir)) {
            $this->_mkdirs(dirname($dir), $mode);
            return @mkdir($dir, $mode);
        }
        return true;
    }
    
    protected function _moveUploadFile($file){
        $fileExt = $this->_ret['fileExt'];
        $destFile = sha1(date('Ymd-His') . ceil(microtime(true) % 1000)) . '.' . $fileExt;
        $destFolder = $this->_imgBaseDir . $this->_imgGroupDir . date('Y').'/'.date('m').'/'.date('d').'/';
        $dest = $destFolder . $destFile;
        $this->_ret['resultFile'] = $destFile;
        $this->_ret['resultFilepath'] = $dest;
        
        $this->_mkdirs($destFolder);
        if (! move_uploaded_file($file['tmp_name'], $dest)) {
            $this->_ret['code'] = -7;
            $this->_ret['msg'] = 'remote move uploaded file failed';
        } else {
            $this->_ret['code'] = 0;
            $this->_ret['url'] = $this->_imgPreUrl . $this->_imgGroupDir . $destFile;
            $this->_ret['msg'] = 'remote upload success';
        }
    }
    
    //服务端处理上传，部署在res.miku.us/cbupl/upimg.php。
    function up($file){
        if (! $this->_check($file)) return $this->_ret;
        $this->_moveUploadFile($file);
        return $this->_ret;
    }
    
    //服务接口编写测试用例
    static function testServer(){
        $server = new ImgUploadServer($_REQUEST['imgGroupDir'] ?: '');
        $ret = $server->up($_FILES['tu']);
        $ret['fileName'] = $_REQUEST['fileName'];
        echo json_encode($ret);
    }
    
}

